home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccppcsrc.lha / vbcc / vlink / main.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  13KB  |  451 lines

  1. /* $VER: vlink main.c V0.6 (24.10.98)
  2.  *
  3.  * This file is part of vlink, a portable linker for multiple
  4.  * object formats.
  5.  * Copyright (c) 1997-99  Frank Wille
  6.  *
  7.  * vlink is freeware and part of the portable and retargetable ANSI C
  8.  * compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
  9.  * vlink may be freely redistributed as long as no modifications are
  10.  * made and nothing is charged for it. Non-commercial usage is allowed
  11.  * without any restrictions.
  12.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  13.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  14.  *
  15.  *
  16.  * v0.6  (24.10.98) phx
  17.  *       -baseoff will modify the base-reg section offset for the
  18.  *       destination target.
  19.  *       Deleted obsolete make_baserel_offsets().
  20.  * v0.5d (22.08.98) phx
  21.  *       Faster memory allocation can be activated by #define FASTALLOC.
  22.  * v0.5  (27.06.98) phx
  23.  *       -v shows default target.
  24.  * v0.4  (05.06.98) phx
  25.  *       -sc forces merging of all code sections in an executable.
  26.  *       -sd forces merging of all data and bss sections in an executable.
  27.  *       -multibase prevents auto-merging of sections, which are accessed
  28.  *       base-relative.
  29.  *       Call linker_relrefs() to find all relative references between
  30.  *       sections.
  31.  * v0.3  (16.04.98) phx
  32.  *       -R directs vlink to generate short relocs, if the target format
  33.  *       allows this. It is for example supported by ELF and AmigaDos.
  34.  *       New option -F for reading a list of input files.
  35.  * v0.2  (07.03.98) phx
  36.  *       -v shows standard library path.
  37.  * v0.1  (27.02.98) phx
  38.  *       First version that seems to link AmigaOS ADOS and EHF
  39.  *       objects and libraries. Many common features, like linking
  40.  *       sections together which have relative references, are
  41.  *       still missing. Also, PowerPC-ELF32 support is about to come.
  42.  * v0.0  (04.08.97) phx
  43.  *       File created. Project started on a beautiful summer-day
  44.  *       at the North Sea beach of Cuxhaven. :)
  45.  */
  46.  
  47.  
  48. #define MAIN_C
  49. #include "vlink.h"
  50.  
  51.  
  52. struct GlobalVars gvars;
  53.  
  54.  
  55. void cleanup(struct GlobalVars *);
  56.  
  57. static char *get_option_arg(int,char *[],int *);
  58. static void ReadListFile(struct GlobalVars *,char *);
  59.  
  60.  
  61.  
  62. main(int argc,char *argv[])
  63. {
  64.   struct GlobalVars *gv = &gvars;
  65.   int i,j;
  66.   char *buf;
  67.   struct LibPath *libp;
  68.   struct InputFile *ifn;
  69.   bool stdlib;
  70.   bool dynamic = TRUE;  /* link with dynamic libraries first */
  71.   int so_version = 0;   /* minum version for shared objects */
  72.  
  73. #ifdef FASTALLOC
  74.   init_mem();
  75. #endif
  76.   /* initialize and set default values */
  77.   memset(gv,0,sizeof(struct GlobalVars));
  78.   initlist(&gv->libpaths);
  79.  
  80. #ifdef LIBPATH
  81.   libp = alloc(sizeof(struct LibPath));
  82.   libp->path = LIBPATH;  /* default search path */
  83.   addtail(&gv->libpaths,&libp->n);
  84.   stdlib = TRUE;
  85. #else
  86.   stdlib = FALSE;
  87. #endif
  88.  
  89. #ifdef DEFTARGET
  90.   for (j=0; fff[j]; j++) {
  91.     if (!strcmp(fff[j]->tname,DEFTARGET)) {
  92.       gv->dest_format = (uint8)j;
  93.       break;
  94.     }
  95.   }
  96.   if (fff[j] == NULL) {
  97.     fprintf(stderr,"Configuration warning: Selected default target "
  98.             "\"%s\" is not included.\nThe current default target "
  99.             "is \"%s\".\n",DEFTARGET,fff[gv->dest_format]->tname);
  100.     printf("\n");
  101.   }
  102. #endif
  103.  
  104.   initlist(&gv->inputlist);
  105.   initlist(&gv->lnksec);
  106.   gv->dest_name = "a.out";
  107.   gv->maxerrors = DEF_MAXERRORS;
  108.  
  109.   if (argc<2 || (argc==2 && *argv[1]=='?')) {
  110.     show_usage();
  111.     exit(EXIT_SUCCESS);
  112.   }
  113.  
  114.   for (i=1; i<argc; i++) {
  115.  
  116.     if (*argv[i] == '-') {  /* option detected */
  117.       switch (argv[i][1]) {
  118.  
  119.         case 'b':  
  120.           if (!strcmp(&argv[i][2],"aseoff")) {  /* set base-relative offset */
  121.             ++i;
  122.             if (i<argc && *argv[i]!='-') {
  123.               long bo;
  124.               sscanf(argv[i],"%li",&bo);
  125.               fff[gv->dest_format]->baseoff = bo;
  126.             }
  127.             else
  128.               error(34,argv[--i]);  /* option requires argument */
  129.           }
  130.  
  131.           else {  /* select target format */
  132.             if (buf = get_option_arg(argc,argv,&i)) {
  133.               for (j=0; fff[j]; j++)
  134.                 if (!strcmp(fff[j]->tname,buf))
  135.                   break;
  136.               if (fff[j])
  137.                 gv->dest_format = (uint8)j;
  138.               else
  139.                 error(9,buf);  /* invalid target format */
  140.             }
  141.             else
  142.               error(5,'b');  /* option requires argument */
  143.           }
  144.           break;
  145.  
  146.         case 'd':
  147.           if (buf = get_option_arg(argc,argv,&i)) {
  148.             switch (*buf) {
  149.               case 'n':  /* static */
  150.                 dynamic = FALSE;
  151.                 break;
  152.               case 'y':  /* dynamic */
  153.                 dynamic = TRUE;
  154.                 break;
  155.               case 'c':
  156.                 gv->alloc_common = TRUE;  /* force alloc. of common syms. */
  157.                 break;
  158.               case 'p':
  159.                 /* @@@ something with procedures... don't know */
  160.                 break;
  161.               default:
  162.                 error(4,*buf);  /* unknown argument for option -d */
  163.                 break;
  164.             }
  165.           }
  166.           else
  167.             error(5,'d');  /* option requires argument */
  168.           break;
  169.  
  170.         case 'h':  /* help text */
  171.           show_usage();
  172.           exit(EXIT_SUCCESS);
  173.  
  174.         case 'l':  /* library specifier */
  175.           if (buf = get_option_arg(argc,argv,&i)) {
  176.             ifn = alloc(sizeof(struct InputFile));
  177.             ifn->name = buf;
  178.             ifn->lib = TRUE;
  179.             ifn->dynamic = dynamic;
  180.             ifn->so_ver = so_version;
  181.             so_version = 0;
  182.             addtail(&gv->inputlist,&ifn->n);
  183.           }
  184.           else
  185.             error(5,'l');  /* option requires argument */
  186.           break;
  187.  
  188.         case 'm':
  189.           if (!strcmp(&argv[i][2],"ultibase"))
  190.             gv->multibase = TRUE;
  191.           else
  192.             error(2,argv[i]);  /* unrecognized option */
  193.           break;
  194.  
  195.         case 'n':
  196.           if (!strcmp(&argv[i][2],"ostdlib")) {
  197.             if (stdlib) {
  198.               remhead(&gv->libpaths);
  199.               stdlib = FALSE;
  200.             }
  201.           }
  202.           else
  203.             error(2,argv[i]);  /* unrecognized option */
  204.           break;
  205.  
  206.         case 'o':  /* set output file name */
  207.           if (!(gv->dest_name = get_option_arg(argc,argv,&i)))
  208.             error(5,'o');  /* option requires argument */
  209.           break;
  210.  
  211.         case 'r':  /* output is an relocatable object again */
  212.           gv->dest_object = TRUE;
  213.           break;
  214.  
  215.         case 's':
  216.           switch (argv[i][2]) {
  217.             case '\0':  /* strip all symbols */
  218.               gv->strip_symbols = STRIP_ALL;
  219.               break;
  220.             case 'c':   /* -sc force small code */
  221.               gv->small_code = TRUE;
  222.               break;
  223.             case 'd':   /* -d force small data */
  224.               gv->small_code = TRUE;
  225.               break;
  226.             case 't':   /* -static */
  227.               dynamic = FALSE;
  228.               break;
  229.             default:
  230.               error(2,argv[i]);  /* unrecognized option */
  231.               break;
  232.           }
  233.           break;
  234.  
  235.         case 't':  /* trace file accesses */
  236.           gv->trace_file = stderr;
  237.           break;
  238.  
  239.         case 'u':  /* mark symbol as undefined */
  240.           /* @@@ ... */
  241.           break;
  242.  
  243.         case 'v':  /* show version and target info */
  244.           show_version();
  245.           printf("Standard library path: %s\nDefault target: %s\n"
  246.                  "Supported targets:", stdlib ? 
  247.                  ((struct LibPath *)(gv->libpaths.first))->path : "none",
  248.                  fff[gv->dest_format]->tname);
  249.           for (j=0; fff[j]; j++)
  250.             printf(" %s",fff[j]->tname);
  251.           printf("\n");
  252.           exit(EXIT_SUCCESS);
  253.  
  254.         case 'w':  /* suppress warnings */
  255.           gv->dontwarn = TRUE;
  256.           break;
  257.  
  258.         case 'x':  /* discard all local symbols */
  259.           gv->discard_local = DISLOC_ALL;
  260.           break;
  261.  
  262.         case 'y':  /* trace all accesses on a specific symbol */
  263.           if (gv->trace_syms == NULL)
  264.             gv->trace_syms = alloc_hashtable(TRSYMHTABSIZE);
  265.           if (buf = get_option_arg(argc,argv,&i)) {
  266.             struct SymNames **chain = 
  267.                             &gv